package com.bootdo.clouddo.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bootdo.clouddo.domain.book.BookCatalogue;
import com.bootdo.clouddo.domain.book.BookCategory;
import com.bootdo.clouddo.domain.book.BookDetail;
import com.bootdo.clouddo.redis.CommonRedisService;
import com.bootdo.clouddo.redis.RedisEnum;
import com.bootdo.clouddo.service.book.IBookCatalogueService;
import com.bootdo.clouddo.service.book.IBookCategoryService;
import com.bootdo.clouddo.service.book.IBookContentService;
import com.bootdo.clouddo.service.book.IBookDetailService;
import com.bootdo.clouddo.utils.R;
import com.bootdo.clouddo.utils.StringUtils;
import com.bootdo.clouddo.utils.book.BookApi;
import com.bootdo.clouddo.utils.book.BookUtils;
import com.bootdo.clouddo.utils.common.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class BookTask {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private CommonRedisService redisService;

    @Autowired
    private IBookDetailService detailService;

    @Autowired
    private IBookCatalogueService catalogueService;

    @Autowired
    private IBookContentService contentService;

    @Autowired
    private IBookCategoryService categoryService;

    @Async("myExecutor")
    @Scheduled(fixedRate = 1000*60*30)
    public void getCategory(){
        getCategoryByMan("male");
        getCategoryByMan("female");
    }

    @Async("myExecutor")
    @Scheduled(fixedRate = 1000*60*30)
    public void getDashboard(){
        getDashboardByMan("male");
        getDashboardByMan("female");
    }

    //@Scheduled(fixedRate = 1000*60*30)
    public void getBookDetail(){
        for (long i = 835114; i < 1000000000; i++) {
            logger.info("begin fetch detail, id: " + i);
            saveDetail(i);
        }
    }


    public void getDashboardByMan(String man){
        try {
            String url = null;
            if(StringUtils.equals("male", man)) {
                url = BookApi.HOME_BOY.getUrl();
            }else {
                url = BookApi.HOME_GIRL.getUrl();
            }
            JSONObject resultVo = BookUtils.fetchJSONObject(url);
            if(resultVo != null && resultVo.size() > 0) {
                redisService.put(RedisEnum.BOOK_DASHBOARD.getKey() + man, resultVo.getJSONArray("info"), RedisEnum.BOOK_DASHBOARD.getExpire());
                redisService.put(RedisEnum.BOOK_BANNER.getKey() + man, resultVo.getJSONArray("banner"), RedisEnum.BOOK_BANNER.getExpire());
                saveDetailArr(resultVo.getJSONArray("info"));
                saveDetailArr(resultVo.getJSONArray("banner"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void getCategoryByMan(String man){
        try {
            JSONArray resultVo = BookUtils.fetchJSONArray(BookApi.CATEGORYS.getUrl() + man);
            if(resultVo != null && resultVo.size() > 0) {
                redisService.put(RedisEnum.BOOK_CATEGORY.getKey() + man, resultVo, RedisEnum.BOOK_CATEGORY.getExpire());
                resultVo.stream().forEach(r -> {
                    BookCategory category = ((JSONObject)r).toJavaObject(BookCategory.class);
                    category.setType(man);
                    category.setUpdateTime(new Date());
                    categoryService.save(category);
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Async
    public void saveDetailArr(JSONArray recordArr){
        if(recordArr == null || recordArr.isEmpty()) {
            return;
        }
        recordArr.stream().forEach(record -> {
            saveDetail((JSONObject) record);
        });
    }

    @Async
    public void saveDetail(long id){
        try{
            JSONObject resultVo = BookUtils.fetchJSONObject(BookApi.DETAIL.getUrl() + id);
            if(resultVo == null) {
                return;
            }
            BookDetail book = resultVo.toJavaObject(BookDetail.class);
            saveDetail(book);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Async
    public void saveDetail(JSONObject record){
        try{
            // 重新请求一次
            JSONObject resultVo = BookUtils.fetchJSONObject(BookApi.DETAIL.getUrl() + record.getLong("id"));
            if(resultVo == null) {
                return;
            }
            BookDetail book = resultVo.toJavaObject(BookDetail.class);
            saveDetail(book);
            // 请求菜单
            saveCatalogue(book);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void saveCatalogue(BookDetail book){
        Map param = new HashMap();
        // 替换无用的siteId
        Integer siteId = book.getSiteId();
        siteId = (siteId == 10) ? 36: siteId;
        // 传参
        param.put("bookId", book.getId());
        param.put("siteId", siteId);
        JSONObject resultVo = BookUtils.fetchJSONObject(BookApi.MENU.getUrl(), param);
        saveCatalogue(resultVo, book.getId(), book.getSiteId());
    }

    @Async
    public void saveCatalogue(JSONObject data, Long bookId, Integer siteId){
        if(data != null && data.getJSONArray("list") != null) {
            redisService.put(RedisEnum.BOOK_CATALOGUE.getKey() + bookId + "_" + siteId, data, RedisEnum.BOOK_CATALOGUE.getExpire());
            String chapter = data.getString("chapter");
            JSONArray list = data.getJSONArray("list");
            if(list == null || list.isEmpty()) {
                return;
            }
            list.stream().forEach(d -> {
                JSONObject jo = (JSONObject)d;
                catalogueService.save(new BookCatalogue(bookId, chapter, siteId, jo.getString("name"), jo.getString("url")));
                saveContent(chapter, siteId, bookId, jo.getString("url"));
            });
        }
    }

    @Async
    public int saveDetail(BookDetail record) {
        if(record == null || record.getId() == null) {
            return -1;
        }
        redisService.put(RedisEnum.BOOK_DETAIL.getKey() + record.getId(), record, RedisEnum.BOOK_DETAIL.getExpire());
        int result = detailService.save(record);

        logger.info("save or update book detail, id: " + record.getId());
        return result;
    }

    @Async
    public int saveContent(String chapter, Integer siteId, Long bookId, String url) {
        if(StringUtils.isBlank(chapter) || StringUtils.isBlank(url) ||
                bookId == null || siteId == null) {
            return -1;
        }
        if(contentService.find(bookId, siteId, url) != null) {
            return 1;
        }
        String chapterUrl = chapter.replace("[chapterid]", url);
        String content = BookUtils.getContent(chapterUrl, siteId);
        if(StringUtils.isBlank(content)) {
            return -1;
        }
        int result = contentService.save(bookId, siteId, chapter, url, content);
        logger.info("save or update book content, id: " + bookId + ", url: " + url);
        return result;
    }
}
